package insight.p6.event;

import insight.common.PropertyLoader;
import insight.common.logging.JLogger;
import insight.primavera.common.P6helper;
import insight.primavera.common.Utils;

import java.io.StringReader;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueReceiver;
import javax.jms.QueueSession;
import javax.jms.TextMessage;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import org.springframework.beans.factory.annotation.Autowired;

import primavera.events.v83.ActivityUpdatedType;
import primavera.events.v83.MessagingObjects;

import com.primavera.common.value.ObjectId;
import com.primavera.integration.client.bo.BOIterator;
import com.primavera.integration.client.bo.enm.ActivityType;
import com.primavera.integration.client.bo.enm.UDFIndicator;
import com.primavera.integration.client.bo.enm.UDFSubjectArea;
import com.primavera.integration.client.bo.object.Activity;
import com.primavera.integration.client.bo.object.ActivityCodeAssignment;

/**
 * This example shows how to establish a connection to and receive messages from
 * a JMS queue. The classes in this package operate on the same JMS queue. Run
 * the classes together to witness messages being sent and received, and to
 * browse the queue for messages. This class is used to receive and remove
 * messages from the queue.
 * 
 * @author Copyright (c) 1999-2005 by BEA Systems, Inc. All Rights Reserved.
 */
public class QueueReceive implements MessageListener {

	static final Logger logger = JLogger
			.getLogger(QueueReceive.class.getName());

	@Autowired
	private P6helper helper;

	// // Defines the JNDI context factory.
	// public final static String JNDI_FACTORY =
	// "weblogic.jndi.WLInitialContextFactory";
	//
	// // Defines the JMS connection factory for the queue.
	// public final static String JMS_FACTORY = PropertyLoader.getProperty(
	// "jms.connection.name", "jms/P6ConnectionFactory");
	//
	// // Defines the queue.
	// public final static String QUEUE = PropertyLoader.getProperty(
	// "jms.queue.name", "jms/PrimaveraQ");
	//
	// private QueueConnectionFactory qconFactory;
	// private QueueConnection qcon;
	// private QueueSession qsession;
	// private QueueReceiver qreceiver;
	// private Queue queue;
	// private boolean quit = false;

	// public QueueReceive() throws Exception {
	// main(new String[]{""});
	// }

	/**
	 * Message listener interface.
	 * 
	 * @param msg
	 *            message
	 */
	public void onMessage(Message msg) {
		try {
			String msgText = "";
			if (msg instanceof TextMessage) {
				msgText = ((TextMessage) msg).getText();
				logger.info("Message Received : " + msgText);
				try {
					logger.fine("Creating Messaging Object");
					JAXBContext jc = JAXBContext
							.newInstance(MessagingObjects.class);
					Unmarshaller u = jc.createUnmarshaller();
					Object obj = u.unmarshal(new StringReader(msgText));
					MessagingObjects msgObj = (MessagingObjects) obj;
					ActivityUpdatedType updObj;
					logger.fine("Check whether its activity updated event");
					if ((updObj = msgObj.getActivityUpdated()) != null) {
						logger.info("A primavera activity updated.");
						updateProjectIndicator(helper.getSession(),
								updObj.getObjectId());
					}
				} catch (JAXBException e) {
					logger.log(Level.SEVERE, e.getMessage(), e);
					e.printStackTrace();
				}
			}

			// System.out.println("Message Received: " + msgText);

			// if (msgText.equalsIgnoreCase("quit")) {
			// synchronized (this) {
			// quit = true;
			// this.notifyAll(); // Notify main thread to quit
			// }
			// }
		} catch (JMSException jmse) {

			logger.log(Level.SEVERE, jmse.getMessage(), jmse);
		}
	}

	// /**
	// * Creates all the necessary objects for receiving messages from a JMS
	// * queue.
	// *
	// * @param ctx
	// * JNDI initial context
	// * @param queueName
	// * name of queue
	// * @exception NamingException
	// * if operation cannot be performed
	// * @exception JMSException
	// * if JMS fails to initialize due to internal error
	// */
	// public void init(Context ctx, String queueName) throws NamingException,
	// JMSException {
	// qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);
	// qcon = qconFactory.createQueueConnection();
	// qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
	// queue = (Queue) ctx.lookup(queueName);
	// qreceiver = qsession.createReceiver(queue);
	// qreceiver.setMessageListener(this);
	// qcon.start();
	// }
	//
	// /**
	// * Closes JMS objects.
	// *
	// * @exception JMSException
	// * if JMS fails to close objects due to internal error
	// */
	// public void close() throws JMSException {
	// qreceiver.close();
	// qsession.close();
	// qcon.close();
	// }

	/**
	 * main() method.
	 * 
	 * @param args
	 *            WebLogic Server URL
	 * @exception Exception
	 *                if execution fails
	 */

	// public static void main(String[] args) throws Exception {
	// // System.setProperty("insight.application.config",
	// // "F:\\Workspaces\\Miescore\\P6MessageQueue");
	// // System.setProperty("primavera.bootstrap.home",
	// // "F:\\Workspaces\\Miescore\\P6MessageQueue\\properties");
	// //
	//
	// // P6helper helper = new P6helper();
	// // com.primavera.integration.client.Session session =
	// // helper.getSession();
	// //
	// // if(session==null){
	// // System.out.println("Session null");
	// // }
	// // System.exit(0);
	//
	// String serverURL = PropertyLoader.getProperty(
	// "primavera.queue.serverurl", "t3://172.17.71.23:7001");
	// InitialContext ic = getInitialContext(serverURL);
	// QueueReceive qr = new QueueReceive();
	// qr.init(ic, QUEUE);
	//
	// System.out
	// .println("JMS Ready To Receive Messages (To quit, send a \"quit\" message).");
	//
	// // Wait until a "quit" message has been received.
	// synchronized (qr) {
	// while (!qr.quit) {
	// try {
	// qr.wait();
	// } catch (InterruptedException ie) {
	// }
	// }
	// }
	// qr.close();
	// }
	//
	// @SuppressWarnings("unchecked")
	// private static InitialContext getInitialContext(String url)
	// throws NamingException {
	// Hashtable env = new Hashtable();
	// env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
	// env.put(Context.PROVIDER_URL, url);
	// return new InitialContext(env);
	// }

	public static void updateProjectIndicator(
			com.primavera.integration.client.Session session, int activityObjId) {
		// P6helper helper = new P6helper();

		try {
			logger.info("Loading activity object Id : " + activityObjId);
			Activity activity = Activity.load(session, new String[] { "Id",
					"ProjectObjectId", "Type", "ActualFinishDate" },
					new ObjectId(activityObjId));

			logger.fine("Check whether activity is FINISH MILESTONE Type");
			if (activity.getType() == ActivityType.FINISH_MILESTONE || activity
							.getType() == ActivityType.MILESTONE) {
				String where = "ActivityCodeTypeName='"
						+ PropertyLoader.getProperty(
								"primavera.milestone.codename", "Drives") + "'";

				logger.info("Loading Activity Code Assignment where " + where);
				BOIterator<ActivityCodeAssignment> itr = activity
						.loadActivityCodeAssignments(
								new String[] { "ActivityCodeValue" }, where,
								null);

				if (itr.hasNext()) {
					ActivityCodeAssignment actAssign = itr.next();
					logger.fine("Getting Activity Code Value");
					String codeValue = actAssign.getActivityCodeValue();

					logger.fine("Getting Activity ProjectObjectId.");
					ObjectId prjObjId = activity.getProjectObjectId();

					logger.info("Code value" + codeValue
							+ " ProjectObjectId : " + prjObjId);
					logger.info("Set UDF value [" + codeValue + "Status"
							+ "] on project");
					Utils.setUDFValueIndicator(session, UDFSubjectArea.PROJECT,
							codeValue + " Status", prjObjId, UDFIndicator.GREEN);
					logger.info("Set UDF value [" + codeValue + "Date"
							+ "] on project");
					Utils.setUDFValueDate(session, UDFSubjectArea.PROJECT,
							codeValue + " Date", prjObjId,
							activity.getActualFinishDate());
				}
			}
		} catch (Exception e) {
			logger.log(Level.SEVERE, e.getMessage(), e);
		}

	}

	public P6helper getHelper() {
		return helper;
	}

	public void setHelper(P6helper helper) {
		this.helper = helper;
	}
}